﻿using System;
using System.Collections.Generic;
using System.Transactions;
using Navigant.Infrastructure.DomainBase;
using Navigant.Infrastructure.RepositoryFramework;

namespace Navigant.Infrastructure
{
    public class UnitOfWork : IUnitOfWork
    {
        private Guid key;
        private Dictionary<IEntity, IUnitOfWorkRepository> addedEntities;
        private Dictionary<IEntity, IUnitOfWorkRepository> changedEntities;
        private Dictionary<IEntity, IUnitOfWorkRepository> deletedEntities;
        private bool useTransactions;

        public UnitOfWork() 
            : this(true)
        {
        }

        public UnitOfWork(bool useTransactions)
        {
            this.key = Guid.NewGuid();
            this.addedEntities = new Dictionary<IEntity, 
                                     IUnitOfWorkRepository>();
            this.changedEntities = new Dictionary<IEntity, 
                                       IUnitOfWorkRepository>();
            this.deletedEntities = new Dictionary<IEntity, 
                                       IUnitOfWorkRepository>();
            this.useTransactions = useTransactions;
        }

        public static IUnitOfWork New()
        {
            return new UnitOfWork();
        }

        #region IUnitOfWork Members

        public void RegisterAdded(IEntity entity, 
            IUnitOfWorkRepository repository)
        {
            this.addedEntities.Add(entity, repository);
        }

        public void RegisterChanged(IEntity entity, 
            IUnitOfWorkRepository repository)
        {
            this.changedEntities.Add(entity, repository);
        }

        public void RegisterRemoved(IEntity entity, 
            IUnitOfWorkRepository repository)
        {
            this.deletedEntities.Add(entity, repository);
        }

        public void Commit()
        {
            //using (TransactionScope scope = new TransactionScope())
            //{
                foreach (IEntity entity in this.deletedEntities.Keys)
                {
                    this.deletedEntities[entity].PersistDeletedItem(entity);
                }

                foreach (IEntity entity in this.addedEntities.Keys)
                {
                    this.addedEntities[entity].PersistNewItem(entity);
                }

                foreach (IEntity entity in this.changedEntities.Keys)
                {
                    this.changedEntities[entity].PersistUpdatedItem(entity);
                }

                if (this.useTransactions)
                {
                    //scope.Complete();
                }
            //}

            this.deletedEntities.Clear();
            this.addedEntities.Clear();
            this.changedEntities.Clear();
            this.key = Guid.NewGuid();
        }

        public object Key
        {
            get { return this.key; }
        }

        public bool UseTransactions
        {
            get { return this.useTransactions; }
            set { this.useTransactions = value; }
        }

        #endregion
    }
}
